package com.googlecode.connectlet.crypto.stream;

public class RC4Cipher extends StreamCipher {
	private static final long serialVersionUID = 1L;

	public static final int MAX_KEY_LENGTH = 256;

	private byte[] key;
	private int[] state = new int[MAX_KEY_LENGTH];
	private int x, y;

	public RC4Cipher(byte[] key) {
		this.key = key;
		reset();
	}

	@Override
	public void reset() {
		x = 0;
		y = 0;
		for (int i = 0; i < MAX_KEY_LENGTH; i ++) {
			state[i] = i;
		}
		int j = 0;
		for (int i = 0; i < MAX_KEY_LENGTH; i ++) {
			j = (j + state[i] + key[i % key.length]) & 0xff;
			swap(i, j);
		}
	}

	@Override
	public int output() {
		x = (x + 1) & 0xff;
		y = (y + state[x]) & 0xff;
		swap(x, y);
		int t = (state[x] + state[y]) & 0xff;
		return state[t];
	}

	private void swap(int i, int j) {
		int t = state[i];
		state[i] = state[j];
		state[j] = t;
	}
}